import warnings
from xml.dom import minidom
from . import SMKernel

#warnings.warn('Models.py is going to be deprecated')

apply_edisp = False

def _get_xml_list(name, fits=None, is_mapcube=False, is_isotropic=False, ra=0., dec=0.):
    xml_list = []
    if (fits is None) and (not is_isotropic):
        xml_list.append('<source name="%s" type="PointSource">' % name)
        xml_list.append('\t<!-- point source units are cm^-2 s^-1 MeV^-1 -->')
        xml_list.append('\t<spatialModel type="SkyDirFunction">')
        if (-360<ra<360) and (-90<dec<90):
            xml_list.append('\t\t<parameter free="0" max="360." min="-360." name="RA" scale="1.0" value="%s"/>'%ra)
            xml_list.append('\t\t<parameter free="0" max="90." min="-90." name="DEC" scale="1.0" value="%s"/>'%dec)
        else:
            raise IOError('Invalid values: ra=%s, dec=%s!' % (ra, dec))
    else:
        xml_list.append('<source name="%s" type="DiffuseSource">' % name)
        xml_list.append('\t<!-- diffuse source units are cm^-2 s^-1 MeV^-1 sr^-1 -->')
        if is_mapcube:
            xml_list.append('\t<spatialModel file="%s" type="MapCubeFunction" map_based_integral="true">' % fits)
            xml_list.append('\t\t<parameter free="0" max="1000.0" min="0.001" name="Normalization" scale="1.0" value="1.0"/>')
        elif is_isotropic:
            xml_list.append('\t<spatialModel type="ConstantValue">')
            xml_list.append('\t\t<parameter free="0" max="10.0" min="0.0" name="Value" scale="1.0" value="1.0"/>')
        else:
            xml_list.append('\t<spatialModel file="%s" type="SpatialMap" map_based_integral="true">' % fits)
            xml_list.append('\t\t<parameter free="0" max="1000.0" min="0.001" name="Prefactor" scale="1.0" value="1.0"/>')
    xml_list.insert(2, '\t</spectrum>')
    xml_list.append('\t</spatialModel>')
    xml_list.append('</source>')
    return xml_list

def PowerLaw(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="PowerLaw">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="PowerLaw">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="PowerLaw">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1000.0" min="0.0001" name="Prefactor" scale="1e-12" value="1."/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="5.0" min="1.0" name="Index" scale="-1.0" value="2.4"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="1000000.0" min="100.0" name="Scale" scale="1.0" value="1000.0"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def PowerLaw2(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="PowerLaw2">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="PowerLaw2">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="PowerLaw2">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1000.0" min="1e-05" name="Integral" scale="1e-08" value="1.0"/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="5.0" min="1.0" name="Index" scale="-1.0" value="2.4"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="200000.0" min="20.0" name="LowerLimit" scale="1.0" value="200.0"/>')
    xml_list.insert(6, '\t\t<parameter free="0" max="200000.0" min="20.0" name="UpperLimit" scale="1.0" value="2e5"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def BrokenPowerLaw(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="BrokenPowerLaw">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="BrokenPowerLaw">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="BrokenPowerLaw">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1000.0" min="0.001" name="Prefactor" scale="1e-09" value="1"/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="5.0" min="1.0" name="Index1" scale="-1.0" value="1.8"/>')
    xml_list.insert(5, '\t\t<parameter free="1" max="1000000.0" min="100.0" name="BreakValue" scale="1.0" value="1000.0"/>')
    xml_list.insert(6, '\t\t<parameter free="1" max="5.0" min="1.0" name="Index2" scale="-1.0" value="2.3"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def SmoothBrokenPowerLaw(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="SmoothBrokenPowerLaw">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="SmoothBrokenPowerLaw">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="SmoothBrokenPowerLaw">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1e5" min="1e-5" name="Prefactor" scale="1e-09" value="1.0"/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="5.0" min="1.0" name="Index1" scale="-1.0" value="1.4"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="1000000.0" min="100.0" name="Scale" scale="1.0" value="200.0"/>')
    xml_list.insert(6, '\t\t<parameter free="1" max="5.0" min="1.0" name="Index2" scale="-1.0" value="2.4"/>')
    xml_list.insert(7, '\t\t<parameter free="1" max="5e5" min="20" name="BreakValue" scale="1.0" value="400"/>')
    xml_list.insert(8, '\t\t<parameter free="0" max="10" min="0.01" name="Beta" scale="1.0" value="0.2"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def LogParabola(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="LogParabola">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="LogParabola">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="LogParabola">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1000.0" min="0.001" name="norm" scale="1e-09" value="1"/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="10" min="0" name="alpha" scale="1.0" value="2.4"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="1e4" min="20" name="Eb" scale="1" value="300."/>')
    xml_list.insert(6, '\t\t<parameter free="1" max="10" min="-10" name="beta" scale="1.0" value="0."/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def ConstantValue(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="ConstantValue">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="ConstantValue">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="ConstantValue">')
    xml_list.insert(3, '\t\t<parameter free="0" max="10" min="0" name="Value" scale="1" value="1"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def FileFunction(name, spectrum_file, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" file="%s" type="FileFunction">' % spectrum_file)
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum file="%s" type="FileFunction">' % spectrum_file)
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" file="%s" type="FileFunction">' % spectrum_file)
    xml_list.insert(3, '\t\t<parameter free="1" max="1e4" min="1e-4" name="Normalization" scale="1" value="1.0"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def PLSuperExpCutoff(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="PLSuperExpCutoff">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="PLSuperExpCutoff">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="PLSuperExpCutoff">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1000" min="1e-05" name="Prefactor" scale="1e-07" value="1"/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="5.0" min="0.0" name="Index1" scale="-1" value="1.7"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="1000000.0" min="100.0" name="Scale" scale="1" value="200"/>')
    xml_list.insert(6, '\t\t<parameter free="1" max="300000" min="500" name="Cutoff" scale="1" value="3000"/>')
    xml_list.insert(7, '\t\t<parameter free="0" max="5" min="0" name="Index2" scale="1" value="1"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def PLSuperExpCutoff2(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="PLSuperExpCutoff2">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="PLSuperExpCutoff2">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="PLSuperExpCutoff2">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1000" min="1e-05" name="Prefactor" scale="1e-07" value="1"/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="5.0" min="0.0" name="Index1" scale="-1" value="1.7"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="1000000.0" min="100.0" name="Scale" scale="1" value="200"/>')
    xml_list.insert(6, '\t\t<parameter free="1" max="1" min="-1" name="Expfactor" scale="1.0" value="0.001"/>')
    xml_list.insert(7, '\t\t<parameter free="0" max="5" min="0" name="Index2" scale="1" value="1"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def PLSuperExpCutoff3(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="PLSuperExpCutoff3">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="PLSuperExpCutoff3">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="PLSuperExpCutoff3">')
    xml_list.insert(3, '\t\t<parameter free="1" max="1000" min="1e-05" name="Prefactor" scale="1e-07" value="1"/>')
    xml_list.insert(4, '\t\t<parameter free="1" max="5.0" min="0.0" name="Index1" scale="-1" value="1.7"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="1000000.0" min="100.0" name="Scale" scale="1" value="200"/>')
    xml_list.insert(6, '\t\t<parameter free="1" max="10" min="0" name="Expfactor2" scale="1.0" value="2"/>')
    xml_list.insert(7, '\t\t<parameter free="0" max="5" min="0" name="Index2" scale="1" value="1"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)

def Gaussian(name, spatial_fits=None, is_mapcube=False, is_isotropic=False, edispon=None, **kwds):
    xml_list = _get_xml_list(name, spatial_fits, is_mapcube, is_isotropic, **kwds)

    if edispon or (edispon is None and apply_edisp):
        xml_list.insert(1, '\t<spectrum apply_edisp="true" type="Gaussian">')
    elif apply_edisp is None:
        xml_list.insert(1, '\t<spectrum type="Gaussian">')
    else:
        xml_list.insert(1, '\t<spectrum apply_edisp="false" type="Gaussian">')

    xml_list.insert(3, '\t\t<parameter free="1" max="1000.0" min="0.001" name="Prefactor" scale="1e-09" value="1"/>')
    xml_list.insert(4, '\t\t<parameter free="0" max="1e5" min="1e3" name="Mean" scale="1.0" value="7e4"/>')
    xml_list.insert(5, '\t\t<parameter free="0" max="1e5" min="30" name="Sigma" scale="1.0" value="1e3"/>')
    xml_string = '\n'.join(xml_list)

    dom = minidom.parseString(xml_string)
    node = dom.childNodes[0]
    return SMKernel.Source(node)
